package com.jijuxie.house.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jijuxie.agent.domain.Agent;
import com.jijuxie.agent.mapper.AgentMapper;
import com.jijuxie.common.exception.ServiceException;
import com.jijuxie.house.domain.HouseAssign;
import com.jijuxie.house.domain.HouseInfo;
import com.jijuxie.house.domain.vo.HouseAssignVO;
import com.jijuxie.house.mapper.HouseAssignMapper;
import com.jijuxie.house.mapper.HouseMapper;
import com.jijuxie.house.service.IHouseAssignService;
import com.jijuxie.system.domain.SysUser;
import com.jijuxie.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 房源分配服务实现
 * 
 * @author jijuxie
 */
@Service
public class HouseAssignServiceImpl extends ServiceImpl<HouseAssignMapper, HouseAssign> implements IHouseAssignService {

    private static final Logger log = LoggerFactory.getLogger(HouseAssignServiceImpl.class);

    @Autowired
    private HouseMapper houseMapper;

    @Autowired
    private AgentMapper agentMapper;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 获取分配列表（分页查询）
     * 
     * @param params 查询参数
     * @return 分页结果
     */
    @Override
    public Page<HouseAssignVO> getAssignList(Map<String, Object> params) {
        try {
            // 获取分页参数并处理可能的异常
            int pageNum = 1;
            int pageSize = 10;
            try {
                if (params.containsKey("pageNum")) {
                    pageNum = Integer.parseInt(params.get("pageNum").toString());
                }
                if (params.containsKey("pageSize")) {
                    pageSize = Integer.parseInt(params.get("pageSize").toString());
                }
            } catch (NumberFormatException e) {
                // 如果解析失败，使用默认值
                log.warn("分页参数解析失败，使用默认值: pageNum={}, pageSize={}", pageNum, pageSize);
            }
            
            // 创建分页对象
            Page<HouseAssign> page = new Page<>(pageNum, pageSize);
            
            // 构建查询条件
            LambdaQueryWrapper<HouseAssign> queryWrapper = new LambdaQueryWrapper<>();
            
            // 处理房源ID查询条件
            if (params.containsKey("houseId") && StringUtils.isNotEmpty(params.get("houseId").toString())) {
                try {
                    Long houseId = Long.valueOf(params.get("houseId").toString());
                    queryWrapper.eq(HouseAssign::getHouseId, houseId);
                } catch (NumberFormatException e) {
                    log.warn("房源ID格式不正确: {}", params.get("houseId"));
                }
            }
            
            // 处理经纪人ID查询条件
            if (params.containsKey("agentId") && StringUtils.isNotEmpty(params.get("agentId").toString())) {
                try {
                    Long agentId = Long.valueOf(params.get("agentId").toString());
                    queryWrapper.eq(HouseAssign::getAgentId, agentId);
                } catch (NumberFormatException e) {
                    log.warn("经纪人ID格式不正确: {}", params.get("agentId"));
                }
            }
            
            // 处理状态查询条件
            if (params.containsKey("status") && StringUtils.isNotEmpty(params.get("status").toString())) {
                queryWrapper.eq(HouseAssign::getStatus, params.get("status").toString());
            }
            
            // 处理经纪人姓名查询条件（需要关联查询）
            if (params.containsKey("agentName") && StringUtils.isNotEmpty(params.get("agentName").toString())) {
                // 先查询符合条件的经纪人ID
                List<Long> agentIds = agentMapper.selectList(
                    new LambdaQueryWrapper<Agent>()
                        .like(Agent::getRealName, params.get("agentName").toString())
                ).stream().map(Agent::getAgentId).collect(Collectors.toList());
                
                if (!agentIds.isEmpty()) {
                    queryWrapper.in(HouseAssign::getAgentId, agentIds);
                } else {
                    // 如果没有找到匹配的经纪人，返回空结果
                    return new Page<>(pageNum, pageSize, 0);
                }
            }
            
            // 添加排序
            queryWrapper.orderByDesc(HouseAssign::getCreateTime);
            
            // 执行查询
            Page<HouseAssign> resultPage = page(page, queryWrapper);
            
            // 转换为VO
            Page<HouseAssignVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
            
            if (resultPage.getRecords() == null || resultPage.getRecords().isEmpty()) {
                voPage.setRecords(new ArrayList<>());
                return voPage;
            }
            
            // 获取所有房源ID、经纪人ID和操作人ID
            List<Long> houseIds = resultPage.getRecords().stream()
                    .map(HouseAssign::getHouseId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
                    
            List<Long> agentIds = resultPage.getRecords().stream()
                    .map(HouseAssign::getAgentId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
                    
            List<Long> operatorIds = resultPage.getRecords().stream()
                    .map(HouseAssign::getAssignBy)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            // 批量查询房源信息
            final Map<Long, HouseInfo> houseMap = new HashMap<>();
            if (!houseIds.isEmpty()) {
                List<HouseInfo> houses = houseMapper.selectBatchIds(houseIds);
                if (houses != null) {
                    houseMap.putAll(houses.stream()
                            .collect(Collectors.toMap(HouseInfo::getHouseId, house -> house, (a, b) -> a)));
                }
            }
            
            // 批量查询经纪人信息
            final Map<Long, Agent> agentMap = new HashMap<>();
            if (!agentIds.isEmpty()) {
                List<Agent> agents = agentMapper.selectBatchIds(agentIds);
                if (agents != null) {
                    agentMap.putAll(agents.stream()
                            .collect(Collectors.toMap(Agent::getAgentId, agent -> agent, (a, b) -> a)));
                }
            }
            
            // 批量查询操作人信息
            final Map<Long, SysUser> userMap = new HashMap<>();
            if (!operatorIds.isEmpty()) {
                List<SysUser> users = userMapper.selectBatchIds(operatorIds);
                if (users != null) {
                    userMap.putAll(users.stream()
                            .collect(Collectors.toMap(SysUser::getUserId, user -> user, (a, b) -> a)));
                }
            }
            
            // 组装VO
            List<HouseAssignVO> voList = resultPage.getRecords().stream().map(assign -> {
                HouseAssignVO vo = new HouseAssignVO();
                vo.setAssignId(assign.getAssignId());
                vo.setHouseId(assign.getHouseId());
                vo.setAgentId(assign.getAgentId());
                vo.setAssignType(assign.getAssignType());
                vo.setAssignTime(assign.getAssignTime());
                vo.setStatus(assign.getStatus());
                vo.setRemark(assign.getRemark());
                
                // 设置房源信息
                HouseInfo house = houseMap.get(assign.getHouseId());
                if (house != null) {
                    vo.setHouseTitle(house.getTitle());
                    StringBuilder address = new StringBuilder();
                    if (StringUtils.isNotBlank(house.getProvince())) {
                        address.append(house.getProvince());
                    }
                    if (StringUtils.isNotBlank(house.getCity())) {
                        address.append(house.getCity());
                    }
                    if (StringUtils.isNotBlank(house.getDistrict())) {
                        address.append(house.getDistrict());
                    }
                    if (StringUtils.isNotBlank(house.getAddress())) {
                        address.append(house.getAddress());
                    }
                    vo.setHouseAddress(address.toString());
                }
                
                // 设置经纪人信息
                Agent agent = agentMap.get(assign.getAgentId());
                if (agent != null) {
                    vo.setAgentName(agent.getRealName());
                    
                    // 获取经纪人对应的用户信息
                    if (agent.getUserId() != null) {
                        SysUser user = userMapper.selectById(agent.getUserId());
                        if (user != null) {
                            vo.setAgentPhone(user.getPhoneNumber());
                        }
                    }
                }
                
                // 设置操作人信息
                if (assign.getAssignBy() != null) {
                    SysUser operator = userMap.get(assign.getAssignBy());
                    if (operator != null) {
                        vo.setAssignByName(operator.getNickName());
                    }
                }
                
                return vo;
            }).collect(Collectors.toList());
            
            voPage.setRecords(voList);
            return voPage;
        } catch (Exception e) {
            log.error("获取分配列表异常: ", e);
            throw new ServiceException("获取分配列表失败: " + e.getMessage());
        }
    }

    /**
     * 自动分配房源给经纪人
     * 根据经纪人的工作量、评分等因素进行合理分配
     * 
     * @param houseId 房源ID
     * @return 分配结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean autoAssignHouse(Long houseId) {
        // 1. 检查房源是否存在
        HouseInfo house = houseMapper.selectById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 2. 检查房源是否已经分配
        LambdaQueryWrapper<HouseAssign> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HouseAssign::getHouseId, houseId)
                .eq(HouseAssign::getStatus, "1");
        if (baseMapper.selectCount(wrapper) > 0) {
            throw new ServiceException("该房源已分配经纪人，请先取消现有分配");
        }

        // 3. 获取可用的经纪人列表（状态为正常的）
        List<Agent> agents = agentMapper.selectList(
                new LambdaQueryWrapper<Agent>()
                        .eq(Agent::getStatus, "1")  // 1-正常状态
                        .orderByAsc(Agent::getAgentId));
                        
        if (agents.isEmpty()) {
            throw new ServiceException("暂无可用经纪人，无法分配");
        }

        // 4. 自动分配算法（这里简化为按ID轮流分配，实际可根据经纪人工作量等因素）
        // 真实场景中可以有更复杂的分配算法，例如：
        // - 考虑经纪人当前负责的房源数量
        // - 考虑经纪人的评分和成交率
        // - 考虑房源与经纪人擅长领域的匹配度
        Agent selectedAgent = agents.get(0);

        // 5. 创建分配记录
        HouseAssign assign = new HouseAssign();
        assign.setHouseId(houseId);
        assign.setAgentId(selectedAgent.getAgentId());
        assign.setAssignType("1");  // 1-自动分配
        assign.setAssignTime(LocalDateTime.now());
        assign.setStatus("1");  // 1-有效
        assign.setCreateTime(LocalDateTime.now());
        assign.setUpdateTime(LocalDateTime.now());
        
        // 6. 保存分配记录
        boolean result = save(assign);
        
        // 7. 更新房源表中的经纪人ID
        if (result) {
            house.setAgentId(selectedAgent.getAgentId());
            houseMapper.updateById(house);
        }
        
        return result;
    }

    /**
     * 手动指定经纪人负责房源
     * 
     * @param houseId 房源ID
     * @param agentId 经纪人ID
     * @param operatorId 操作人ID
     * @param remark 备注信息
     * @return 分配结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean manualAssignHouse(Long houseId, Long agentId, Long operatorId, String remark) {
        // 1. 检查房源是否存在
        HouseInfo house = houseMapper.selectById(houseId);
        if (house == null) {
            throw new ServiceException("房源不存在");
        }

        // 2. 检查经纪人是否存在
        Agent agent = agentMapper.selectById(agentId);
        if (agent == null) {
            throw new ServiceException("经纪人不存在");
        }
        
        if (!"1".equals(agent.getStatus())) {
            throw new ServiceException("该经纪人状态异常，无法分配");
        }

        // 3. 查询该房源的所有有效分配记录
        LambdaQueryWrapper<HouseAssign> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HouseAssign::getHouseId, houseId)
                .eq(HouseAssign::getStatus, "1");
        List<HouseAssign> existingAssigns = baseMapper.selectList(wrapper);
        
        // 4. 检查是否已经分配给了相同的经纪人
        HouseAssign existingSameAgentAssign = null;
        
        if (!existingAssigns.isEmpty()) {
            // 查找是否存在分配给相同经纪人的记录
            existingSameAgentAssign = existingAssigns.stream()
                    .filter(a -> a.getAgentId().equals(agentId))
                    .findFirst()
                    .orElse(null);
            
            // 将所有现有分配设为无效
            for (HouseAssign existing : existingAssigns) {
                existing.setStatus("0");  // 0-无效
                existing.setUpdateTime(LocalDateTime.now());
                baseMapper.updateById(existing);
            }
        }
        
        boolean result;
        
        // 5. 如果之前已分配给同一经纪人，则更新该记录而不是创建新记录
        if (existingSameAgentAssign != null) {
            existingSameAgentAssign.setStatus("1");  // 重新激活
            existingSameAgentAssign.setAssignType("2");  // 2-手动指定
            existingSameAgentAssign.setAssignTime(LocalDateTime.now());
            existingSameAgentAssign.setAssignBy(operatorId);
            existingSameAgentAssign.setRemark(remark);
            existingSameAgentAssign.setUpdateTime(LocalDateTime.now());
            
            result = updateById(existingSameAgentAssign);
        } else {
            // 6. 创建新的分配记录
            HouseAssign assign = new HouseAssign();
            assign.setHouseId(houseId);
            assign.setAgentId(agentId);
            assign.setAssignType("2");  // 2-手动指定
            assign.setAssignTime(LocalDateTime.now());
            assign.setStatus("1");  // 1-有效
            assign.setAssignBy(operatorId);
            assign.setRemark(remark);
            assign.setCreateTime(LocalDateTime.now());
            assign.setUpdateTime(LocalDateTime.now());
            
            result = save(assign);
        }
        
        // 7. 更新房源表中的经纪人ID
        if (result) {
            house.setAgentId(agentId);
            houseMapper.updateById(house);
        }
        
        return result;
    }

    /**
     * 取消房源分配
     * 
     * @param houseId 房源ID
     * @param agentId 经纪人ID
     * @return 取消结果
     */
    @Override
    public boolean cancelAssign(Long houseId, Long agentId) {
        // 1. 检查分配是否存在
        LambdaQueryWrapper<HouseAssign> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HouseAssign::getHouseId, houseId)
                .eq(HouseAssign::getAgentId, agentId)
                .eq(HouseAssign::getStatus, "1");
        
        HouseAssign assign = baseMapper.selectOne(wrapper);
        if (assign == null) {
            throw new ServiceException("未找到该房源与经纪人的分配关系");
        }
        
        // 2. 修改状态为无效
        assign.setStatus("0");
        assign.setUpdateTime(LocalDateTime.now());
        boolean result = updateById(assign);
        
        // 3. 清空房源表中的经纪人ID
        if (result) {
            HouseInfo house = houseMapper.selectById(houseId);
            if (house != null && house.getAgentId() != null && house.getAgentId().equals(agentId)) {
                house.setAgentId(null);
                houseMapper.updateById(house);
            }
        }
        
        return result;
    }

    /**
     * 获取房源分配情况
     * 
     * @param houseId 房源ID
     * @return 分配列表
     */
    @Override
    public List<HouseAssignVO> getHouseAssignList(Long houseId) {
        // 查询该房源的分配记录
        List<HouseAssign> assigns = baseMapper.selectAssignsByHouseId(houseId);
        if (assigns.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 转换为VO
        List<HouseAssignVO> result = new ArrayList<>(assigns.size());
        
        // 获取房源信息
        HouseInfo house = houseMapper.selectById(houseId);
        
        for (HouseAssign assign : assigns) {
            HouseAssignVO vo = new HouseAssignVO();
            vo.setAssignId(assign.getAssignId());
            vo.setHouseId(assign.getHouseId());
            
            // 设置房源信息
            if (house != null) {
                vo.setHouseTitle(house.getTitle());
                vo.setHouseAddress(house.getProvince() + house.getCity() + house.getDistrict() + house.getAddress());
            }
            
            vo.setAgentId(assign.getAgentId());
            
            // 获取经纪人信息
            Agent agent = agentMapper.selectById(assign.getAgentId());
            if (agent != null) {
                vo.setAgentName(agent.getRealName());
                
                // 获取经纪人对应的用户信息（电话）
                SysUser user = userMapper.selectById(agent.getUserId());
                if (user != null) {
                    vo.setAgentPhone(user.getPhoneNumber());
                }
            }
            
            vo.setAssignType(assign.getAssignType());
            vo.setAssignTime(assign.getAssignTime());
            vo.setStatus(assign.getStatus());
            vo.setRemark(assign.getRemark());
            
            // 获取操作人信息
            if (assign.getAssignBy() != null) {
                SysUser operator = userMapper.selectById(assign.getAssignBy());
                if (operator != null) {
                    vo.setAssignByName(operator.getNickName());
                }
            }
            
            result.add(vo);
        }
        
        return result;
    }

    /**
     * 获取经纪人负责的房源列表
     * 
     * @param page 分页参数
     * @param agentId 经纪人ID
     * @return 房源分页列表
     */
    @Override
    public Page<HouseAssignVO> getAgentHouseList(Page<HouseAssignVO> page, Long agentId) {
        // 分页查询经纪人负责的房源分配记录
        // 由于需要关联多表，这里简化处理，实际项目中可能需要自定义SQL
        
        // 1. 查询分配记录
        LambdaQueryWrapper<HouseAssign> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HouseAssign::getAgentId, agentId)
                .eq(HouseAssign::getStatus, "1")
                .orderByDesc(HouseAssign::getAssignTime);
                
        Page<HouseAssign> assignPage = new Page<>(page.getCurrent(), page.getSize());
        Page<HouseAssign> assignResult = baseMapper.selectPage(assignPage, wrapper);
        
        // 2. 转换结果
        List<HouseAssignVO> records = new ArrayList<>();
        
        for (HouseAssign assign : assignResult.getRecords()) {
            HouseAssignVO vo = new HouseAssignVO();
            vo.setAssignId(assign.getAssignId());
            vo.setHouseId(assign.getHouseId());
            
            // 获取房源信息
            HouseInfo house = houseMapper.selectById(assign.getHouseId());
            if (house != null) {
                vo.setHouseTitle(house.getTitle());
                vo.setHouseAddress(house.getProvince() + house.getCity() + house.getDistrict() + house.getAddress());
            }
            
            vo.setAgentId(assign.getAgentId());
            
            // 获取经纪人信息
            Agent agent = agentMapper.selectById(assign.getAgentId());
            if (agent != null) {
                vo.setAgentName(agent.getRealName());
                
                // 获取经纪人对应的用户信息（电话）
                SysUser user = userMapper.selectById(agent.getUserId());
                if (user != null) {
                    vo.setAgentPhone(user.getUsername());
                }
            }
            
            vo.setAssignType(assign.getAssignType());
            vo.setAssignTime(assign.getAssignTime());
            vo.setStatus(assign.getStatus());
            
            // 获取操作人信息
            if (assign.getAssignBy() != null) {
                SysUser operator = userMapper.selectById(assign.getAssignBy());
                if (operator != null) {
                    vo.setAssignByName(operator.getUsername());
                }
            }
            
            vo.setRemark(assign.getRemark());
            
            records.add(vo);
        }
        
        // 3. 设置分页结果
        Page<HouseAssignVO> result = new Page<>(page.getCurrent(), page.getSize(), assignResult.getTotal());
        result.setRecords(records);
        
        return result;
    }

    /**
     * 获取待分配的房源列表
     * 
     * @return 未分配的房源列表
     */
    @Override
    public List<HouseInfo> getUnassignedHouses() {
        // 直接查询house_info表中agent_id为NULL的房源
        LambdaQueryWrapper<HouseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(HouseInfo::getAgentId)
                .ne(HouseInfo::getStatus, "3") // 排除已下架房源
                .ne(HouseInfo::getStatus, "4") // 排除审核未通过房源
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的房源
                .orderByDesc(HouseInfo::getCreateTime);
        
        return houseMapper.selectList(wrapper);
    }
    
    /**
     * 分页获取待分配的房源列表
     * 
     * @param page 分页参数
     * @return 未分配的房源分页列表
     */
    @Override
    public Page<HouseInfo> getUnassignedHousesPage(Page<HouseInfo> page) {
        // 分页查询house_info表中agent_id为NULL的房源
        LambdaQueryWrapper<HouseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(HouseInfo::getAgentId)
                .ne(HouseInfo::getStatus, "3") // 排除已下架房源
                .ne(HouseInfo::getStatus, "4") // 排除审核未通过房源
                .eq(HouseInfo::getDelFlag, "0") // 只查询未删除的房源
                .orderByDesc(HouseInfo::getCreateTime);
        
        return houseMapper.selectPage(page, wrapper);
    }
} 